﻿using Furion.Authorization;
using Furion.DataEncryption;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using MyFurion.Application;
using MyFurion.Unility.Generic;

namespace MyFurion.Start
{
    /// <summary>
    /// JWT身份认证
    /// </summary>
    public class JwtHandler : AppAuthorizeHandler
    {
        /// <summary>
        /// 管道请求
        /// </summary>
        /// <param name="context"></param>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
        {
            // 这里写您的授权判断逻辑，授权通过返回 true，否则返回 false
            //return Task.FromResult(true);
            RedisCacheHelper redisCacheHelper=App.GetService<RedisCacheHelper>();
            //获取权限标识属性
            ControllerActionDescriptor controllerActionDescriptor = httpContext.GetControllerActionDescriptor();
            var perFilterAttr = (ActionPermission)controllerActionDescriptor.MethodInfo.GetCustomAttributes(typeof(ActionPermission), true).FirstOrDefault(a => a.GetType().Equals(typeof(ActionPermission)));
            bool hasPermi = false;
            //API 权限认证
            if (App.User != null && perFilterAttr != null)
            {
                //超级管理员默认拥有全部权限
                if (CurrentUserInfo.IsSuperAdmin)
                {
                    hasPermi = true;
                }
                else
                {
                    //判断是否有调用接口的权限
                    string permission = perFilterAttr.Permission;
                    if (!string.IsNullOrEmpty(permission))
                    {
                        //缓存中获取当前用户操作权限
                        string actionPer = redisCacheHelper.GetReidsCache(CurrentUserInfo.UserId + CommonConst.ActionPer_Flag);
                        if (!string.IsNullOrWhiteSpace(actionPer))
                        {
                            List<string> perms = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(actionPer);
                            var perArrary = permission.Split(',', StringSplitOptions.RemoveEmptyEntries);
                            hasPermi = perms.Any(f => perArrary.Contains(f));
                        }                      
                    }
                }
            }
            return Task.FromResult(hasPermi);
        }
        /// <summary>
        /// 重写 Handler 添加自动刷新
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task HandleAsync(AuthorizationHandlerContext context)
        {
            //判断Token和RefreshToken是否加入黑名单，如果加入黑名单，则返回403
            RedisCacheHelper redisCacheHelper = App.GetService<RedisCacheHelper>();
            string token = "";//token
            string blackToken ="";//黑名单token
            string refreshToken = "";//refreshtoken
            string blackRefreshToken = "";//黑名单refreshtoken
            if (App.HttpContext.Request.Headers.ContainsKey("Authorization"))
            {
                token = App.HttpContext.Request.Headers["Authorization"];
                if (!string.IsNullOrWhiteSpace(token))
                {
                    blackToken = redisCacheHelper.GetReidsCache(token);
                }
            }
            if (App.HttpContext.Request.Headers.ContainsKey("X-Authorization"))
            {
                refreshToken = App.HttpContext.Request.Headers["X-Authorization"];
                if (!string.IsNullOrWhiteSpace(refreshToken))
                {
                    blackRefreshToken = redisCacheHelper.GetReidsCache(refreshToken);
                }
            }
            if (!string.IsNullOrWhiteSpace(blackToken)||!string.IsNullOrWhiteSpace(blackRefreshToken))
            {
                context.Fail(); // 403
                DefaultHttpContext currentHttpContext = context.GetCurrentHttpContext();
                if (currentHttpContext == null)
                {
                    return;
                }
                currentHttpContext.SignoutToSwagger();
            }
            // 自动刷新Token  根据Request中headers中的Authorization（token） 和 X-Authorization(刷新token)生成新的token
            // 如果 token 无效才会根据 有效期内的刷新token生成新的token以及新的刷新token,否则401
            //生成的token 会在 HttpContext.Response.Headers["x-access-token"](刷新token)和HttpContext.Response.Headers["access-token"]（token）
            if (JWTEncryption.AutoRefreshToken(context, context.GetCurrentHttpContext(),App.GetOptions<JWTSettingsOptions>().ExpiredTime))
            {
                await AuthorizeHandleAsync(context);
            }
            else
            {
                context.Fail(); // 授权失败 401
                DefaultHttpContext currentHttpContext = context.GetCurrentHttpContext();
                if (currentHttpContext == null)
                {
                    return;
                }
                currentHttpContext.SignoutToSwagger();
            }
        }
    }
}
